/*********************************************************************************************************************
 * COPYRIGHT NOTICE
 * Copyright (c) 2018,逐飞科技
 * All rights reserved.
 * 技术讨论QQ群：	一群：179029047(已满)
 *					二群：244861897(已满)
 *					三群：824575535
 *
 * 以下所有内容版权均属逐飞科技所有，未经允许不得用于商业用途，
 * 欢迎各位使用并传播本程序，修改内容时必须保留逐飞科技的版权声明。
 *
 * @file			seekfree_vl53l0x.h
 * @company			成都逐飞科技有限公司
 * @author			逐飞科技(QQ3184284598)
 * @version			查看doc内version文件 版本说明
 * @Software		IAR 8.3 or MDK 5.24
 * @Taobao			https://seekfree.taobao.com/
 * @date			2020-03-25
 * @note			本文件作为IOT开发板seekfree_vl53l0x传感器API
 ********************************************************************************************************************/

#ifndef _SEEKFREE_VL53L0X_H_
#define _SEEKFREE_VL53L0X_H_

#ifdef IOT_BOARD
#include "iot_flexcomm_iic.h"
#else
#include "zf_iic.h"
#endif


// Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs
// from register value
// based on VL53L0X_decode_vcsel_period()
#define decodeVcselPeriod(reg_val)      (((reg_val) + 1) << 1)

// Encode VCSEL pulse period register value from period in PCLKs
// based on VL53L0X_encode_vcsel_period()
#define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1)

// Calculate macro period in *nanoseconds* from VCSEL period in PCLKs
// based on VL53L0X_calc_macro_period_ps()
// PLL_period_ps = 1655; macro_period_vclks = 2304
#define calcMacroPeriod(vcsel_period_pclks) ((((uint32_t)2304 * (vcsel_period_pclks) * 1655) + 500) / 1000)

enum regAddr
{
	SYSRANGE_START									= 0x00,

	SYSTEM_THRESH_HIGH								= 0x0C,
	SYSTEM_THRESH_LOW								= 0x0E,

	SYSTEM_SEQUENCE_CONFIG							= 0x01,
	SYSTEM_RANGE_CONFIG								= 0x09,
	SYSTEM_INTERMEASUREMENT_PERIOD					= 0x04,

	SYSTEM_INTERRUPT_CONFIG_GPIO					= 0x0A,

	GPIO_HV_MUX_ACTIVE_HIGH							= 0x84,

	SYSTEM_INTERRUPT_CLEAR							= 0x0B,

	RESULT_INTERRUPT_STATUS							= 0x13,
	RESULT_RANGE_STATUS								= 0x14,

	RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN			= 0xBC,
	RESULT_CORE_RANGING_TOTAL_EVENTS_RTN			= 0xC0,
	RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF			= 0xD0,
	RESULT_CORE_RANGING_TOTAL_EVENTS_REF			= 0xD4,
	RESULT_PEAK_SIGNAL_RATE_REF						= 0xB6,

	ALGO_PART_TO_PART_RANGE_OFFSET_MM				= 0x28,

	I2C_SLAVE_DEVICE_ADDRESS						= 0x8A,

	MSRC_CONFIG_CONTROL								= 0x60,

	PRE_RANGE_CONFIG_MIN_SNR						= 0x27,
	PRE_RANGE_CONFIG_VALID_PHASE_LOW				= 0x56,
	PRE_RANGE_CONFIG_VALID_PHASE_HIGH				= 0x57,
	PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT				= 0x64,

	FINAL_RANGE_CONFIG_MIN_SNR						= 0x67,
	FINAL_RANGE_CONFIG_VALID_PHASE_LOW				= 0x47,
	FINAL_RANGE_CONFIG_VALID_PHASE_HIGH				= 0x48,
	FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT		= 0x44,

	PRE_RANGE_CONFIG_SIGMA_THRESH_HI				= 0x61,
	PRE_RANGE_CONFIG_SIGMA_THRESH_LO				= 0x62,

	PRE_RANGE_CONFIG_VCSEL_PERIOD					= 0x50,
	PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI				= 0x51,
	PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO				= 0x52,

	SYSTEM_HISTOGRAM_BIN							= 0x81,
	HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT			= 0x33,
	HISTOGRAM_CONFIG_READOUT_CTRL					= 0x55,

	FINAL_RANGE_CONFIG_VCSEL_PERIOD					= 0x70,
	FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI			= 0x71,
	FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO			= 0x72,
	CROSSTALK_COMPENSATION_PEAK_RATE_MCPS			= 0x20,

	MSRC_CONFIG_TIMEOUT_MACROP						= 0x46,

	SOFT_RESET_GO2_SOFT_RESET_N						= 0xBF,
	IDENTIFICATION_MODEL_ID							= 0xC0,
	IDENTIFICATION_REVISION_ID						= 0xC2,

	OSC_CALIBRATE_VAL								= 0xF8,

	GLOBAL_CONFIG_VCSEL_WIDTH						= 0x32,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_0				= 0xB0,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_1				= 0xB1,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_2				= 0xB2,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_3				= 0xB3,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_4				= 0xB4,
	GLOBAL_CONFIG_SPAD_ENABLES_REF_5				= 0xB5,

	GLOBAL_CONFIG_REF_EN_START_SELECT				= 0xB6,
	DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD				= 0x4E,
	DYNAMIC_SPAD_REF_EN_START_OFFSET				= 0x4F,
	POWER_MANAGEMENT_GO1_POWER_FORCE				= 0x80,

	VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV				= 0x89,

	ALGO_PHASECAL_LIM								= 0x30,
	ALGO_PHASECAL_CONFIG_TIMEOUT					= 0x30,
};

typedef enum
{
	VcselPeriodPreRange,
	VcselPeriodFinalRange
}vcselPeriodType;

typedef struct
{
	bool tcc;
	bool msrc;
	bool dss;
	bool pre_range;
	bool final_range;
}SequenceStepEnables;

typedef struct
{
	uint16_t pre_range_vcsel_period_pclks;
	uint16_t final_range_vcsel_period_pclks;

	uint16_t msrc_dss_tcc_mclks;
	uint16_t pre_range_mclks;
	uint16_t final_range_mclks;
	uint32_t msrc_dss_tcc_us;
	uint32_t pre_range_us;
	uint32_t final_range_us;
}SequenceStepTimeouts;


#ifdef IOT_BOARD
bool		vl53l0x_init								(iot_flexcomm_index_list Index);

void		vl53l0x_set_signal_rate_limit				(iot_flexcomm_index_list Index, float limit_Mcps);
float		vl53l0x_get_signal_rate_limit				(iot_flexcomm_index_list Index);

bool		vl53l0x_set_measurement_timing_budget		(iot_flexcomm_index_list Index , uint32_t budget_us);
uint32_t	vl53l0x_get_measurement_timing_budget		(iot_flexcomm_index_list Index);

bool		vl53l0x_set_vcsel_pulse_period				(iot_flexcomm_index_list Index, vcselPeriodType type, uint8_t period_pclks);
uint8_t		vl53l0x_get_vcsel_pulse_period				(iot_flexcomm_index_list Index, vcselPeriodType type);

void		vl53l0x_start_continuous					(iot_flexcomm_index_list Index, uint32_t period_ms);
void		vl53l0x_stop_continuous						(iot_flexcomm_index_list Index);

uint16_t	vl53l0x_read_range_continuous_millimeters	(iot_flexcomm_index_list Index);
uint16_t	vl53l0x_read_range_single_millimeters		(iot_flexcomm_index_list Index);

bool		vl53l0x_get_spad_info						(iot_flexcomm_index_list Index, uint8_t * count, bool * type_is_aperture);

void		vl53l0x_get_sequence_step_enables			(iot_flexcomm_index_list Index, SequenceStepEnables * enables);
void		vl53l0x_get_sequence_step_timeouts			(iot_flexcomm_index_list Index, SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts);

bool		vl53l0x_perform_single_ref_calibration		(iot_flexcomm_index_list Index, uint8_t vhv_init_byte);
#else
bool		vl53l0x_init								(flexcomm_index_list Index);

void		vl53l0x_set_signal_rate_limit				(flexcomm_index_list Index, float limit_Mcps);
float		vl53l0x_get_signal_rate_limit				(flexcomm_index_list Index);

bool		vl53l0x_set_measurement_timing_budget		(flexcomm_index_list Index , uint32_t budget_us);
uint32_t	vl53l0x_get_measurement_timing_budget		(flexcomm_index_list Index);

bool		vl53l0x_set_vcsel_pulse_period				(flexcomm_index_list Index, vcselPeriodType type, uint8_t period_pclks);
uint8_t		vl53l0x_get_vcsel_pulse_period				(flexcomm_index_list Index, vcselPeriodType type);

void		vl53l0x_start_continuous					(flexcomm_index_list Index, uint32_t period_ms);
void		vl53l0x_stop_continuous						(flexcomm_index_list Index);

uint16_t	vl53l0x_read_range_continuous_millimeters	(flexcomm_index_list Index);
uint16_t	vl53l0x_read_range_single_millimeters		(flexcomm_index_list Index);

bool		vl53l0x_get_spad_info						(flexcomm_index_list Index, uint8_t * count, bool * type_is_aperture);

void		vl53l0x_get_sequence_step_enables			(flexcomm_index_list Index, SequenceStepEnables * enables);
void		vl53l0x_get_sequence_step_timeouts			(flexcomm_index_list Index, SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts);

bool		vl53l0x_perform_single_ref_calibration		(flexcomm_index_list Index, uint8_t vhv_init_byte);
#endif

uint16_t	vl53l0x_decode_timeout						(uint16_t reg_val);
uint16_t	vl53l0x_encode_timeout						(uint16_t timeout_mclks);
uint32_t	vl53l0x_timeout_mclks_to_microseconds		(uint16_t timeout_period_mclks, uint8_t vcsel_period_pclks);
uint32_t	vl53l0x_timeout_microseconds_to_mclks		(uint32_t timeout_period_us, uint8_t vcsel_period_pclks);

#endif
